/*This file is part of WZLibCP.

 *  WZLibCP is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

 *  WZLibCP is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
    along with WZLibCP.  If not, see <http://www.gnu.org/licenses/>.
		
	Author: calc0000
*/
#include "stdafx.h"
#include "WZPNGProperty.h"

#include <vector>
#include <iostream>

#include "lodepng.h"

#include "WZCrypto.h"

using namespace std;

namespace WZLib{
	int				WZPNGProperty::width(){return this->_width;}
	int				WZPNGProperty::height(){return this->_height;}
	SDL_Surface*	WZPNGProperty::png(){return this->_png;}
	int				WZPNGProperty::format(){return this->_format+this->_format2;}
	bool			WZPNGProperty::pngParsed(){return this->_pngParsed;}
	ctor WZPNGProperty::WZPNGProperty(WZImage* parent,string name,WZBinaryReader* reader):WZImageProperty(parent,WZImageProperty::Prop_PNG,name,WZObject::Property){
		this->_width=0;
		this->_height=0;
		this->_format=0;
		this->_format2=0;
		this->_offset=-1;
		this->_compBytes=NULL;
		this->_reader=reader;
		this->_png=NULL;
		this->_pngParsed=false;
		if(this->_reader!=NULL){
			this->_width=this->_reader->ReadCompressedInt();
			this->_height=this->_reader->ReadCompressedInt();
			this->_format=this->_reader->ReadCompressedInt();
			this->_format2=this->_reader->ReadByte();
			this->_reader->IncPosition(4);
			int len=this->_reader->ReadInt32();
			this->_length=len;
			this->_reader->IncPosition(1);
			if(len>0)
				this->_compBytes=new byte[len];
			this->_offset=this->_reader->Position();
				int i=3;
			if(len>0)
				this->_reader->_fread(this->_compBytes,sizeof(byte),len);
			this->_parsed=true;
		}
	}
	dtor WZPNGProperty::~WZPNGProperty(){
		SDL_FreeSurface(this->_png);
		delete this->_compBytes;
	}
	ErrorCode WZPNGProperty::parse(WZBinaryReader* reader){
		long currentPos=this->_reader->Position();
		this->_reader->Position(this->_offset);
		vector<byte> decBufTemp;
		vector<byte> compBufTemp;
		unsigned short header=this->_reader->ReadInt16();
		if(header==0x9C78){
			this->_reader->IncPosition(-2);
			for(int i=0;i<this->_length;i++)
				compBufTemp.push_back(this->_compBytes[i]);
			LodeZlib::decompress(decBufTemp,compBufTemp);
		}else{
			this->_reader->IncPosition(-2);
			int blocksize=0;
			int eop=this->_length;
			while(_reader->Position()<eop){
				blocksize=_reader->ReadInt32();
				for(int i=0;i<blocksize;i++){
					compBufTemp.push_back(_reader->ReadByte()^WZCrypto::WZKey[i]);
				}
			}
			LodeZlib::decompress(decBufTemp,compBufTemp);
		}
		vector<byte> argb=vector<byte>(decBufTemp.size()*2);
		int f=this->_format+this->_format2;
		SDL_Surface* opng=NULL;
		switch(f){
			case 1:
				this->_png=SDL_CreateRGBSurface(SDL_HWSURFACE|SDL_SRCALPHA,this->_width,this->_height,32,0,0,0,SDL_ALPHA_TRANSPARENT);
				SDL_FillRect(this->_png,NULL,SDL_MapRGBA(this->_png->format,0,0,0,SDL_ALPHA_TRANSPARENT));
				opng=this->_png;
				this->_png=SDL_DisplayFormatAlpha(this->_png);
				int x,y;int num6,num7,num8,num9;x=0;y=0;
				if(SDL_MUSTLOCK(this->_png))
					SDL_LockSurface(this->_png);
				for(int k=0;k<decBufTemp.size();k+=2){
					if(x==this->_width){
						x=0;
						y++;
						if(y==this->_height)
							break;
					}
					num9 = decBufTemp[k] & 15;
					num9 |= num9 << 4;
					num8 = decBufTemp[k] & 240;
					num8 |= num8 >> 4;
					num7 = decBufTemp[k + 1] & 15;
					num7 |= num7 << 4;
					num6 = decBufTemp[k + 1] & 240;
					num6 |= num6 >> 4;
					*((Uint32*)_png->pixels+y*_png->pitch/4+x)=SDL_MapRGBA(_png->format,num7,num8,num9,num6);
					x++;
				}
				if(SDL_MUSTLOCK(this->_png))
					SDL_UnlockSurface(this->_png);
				break;
			case 513:
				x=y=num6=num7=num8=num9=0;
				this->_png=SDL_CreateRGBSurface(SDL_HWSURFACE|SDL_SRCALPHA,this->_width,this->_height,32,0,0,0,SDL_ALPHA_TRANSPARENT);
				SDL_FillRect(this->_png,NULL,SDL_MapRGBA(this->_png->format,0,0,0,SDL_ALPHA_TRANSPARENT));
				opng=this->_png;
				this->_png=SDL_DisplayFormatAlpha(this->_png);
				if(SDL_MUSTLOCK(this->_png))
					SDL_LockSurface(this->_png);
				for(int k=0;k<decBufTemp.size();k+=2){
					if(x==this->_width){
						x=0;
						y++;
						if(y==this->_height)
							break;
					}
					num9 = (decBufTemp[k] & 0x1f) << 3;
					num9 |= num9 >> 5;
					num8 = ((decBufTemp[k + 1] & 7) << 5) | ((decBufTemp[k] & 0xe0) >> 3);
					num8 |= num8 >> 6;
					num7 = decBufTemp[k + 1] & 0xf8;
					num7 |= num7 >> 5;
					num6 = 0xff;
					*((Uint32*)_png->pixels+y*_png->pitch/4+x)=SDL_MapRGBA(_png->format,num7,num8,num9,num6);//*/
					x++;
				}
				if(SDL_MUSTLOCK(this->_png))
					SDL_UnlockSurface(this->_png);
				break;
			default:
				int i;i=3;
		}
		SDL_FreeSurface(opng);
		this->_parsed=true;
		this->_pngParsed=true;
		return Error_NoError;
	}
};